package com.yunxin.admin.system.api.download;

import com.fasterxml.jackson.core.type.TypeReference;
import com.yunxin.admin.system.api.download.command.AddDownloadMethodCommand;
import com.yunxin.admin.system.api.download.command.DownloadRecordPageCommand;
import com.yunxin.admin.system.api.download.command.UpdateDownloadMethodCommand;
import com.yunxin.admin.system.api.download.command.UpdateDownloadRecordStatusCommand;
import com.yunxin.admin.system.api.download.dto.AdminDownloadRecordPageDTO;
import com.yunxin.admin.system.api.download.extenal.DownloadRecordPageDTO;
import com.yunxin.admin.system.api.download.extenal.converter.DownloadConverter;
import com.yunxin.admin.system.infra.common.constant.SecurityConstants;
import com.yunxin.admin.system.infra.framework.security.util.SecurityUtils;
import com.yunxin.common.exception.BusinessException;
import com.yunxin.common.result.PageResult;
import com.yunxin.common.result.Result;
import com.yunxin.common.result.ResultCode;
import com.yunxin.common.utils.OkHttpUtils;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;
import java.util.UUID;

/**
 * @author zero°
 * @since 2023-06-15
 */
@Tag(name = "1.下载配置")
@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("/download")
public class DownloadConfigController {

    @Value("${download.server.url}")
    private String downloadServerUrl;

    private final DownloadConverter downloadConverter;

    private static final String SYSTEM_CODE = "yunxin-server";


    @Operation(summary = "分页查询下载记录", security = {@SecurityRequirement(name = SecurityConstants.TOKEN_KEY)})
    @PostMapping("/downloadRecordPageQuery")
    public PageResult<AdminDownloadRecordPageDTO> downloadRecordPageQuery(@Validated @RequestBody DownloadRecordPageCommand command) {
        command.setDownloaderName(SecurityUtils.X.getUser().getUsername());
        PageResult<DownloadRecordPageDTO> result = OkHttpUtils.X.post(downloadServerUrl + "/download/record/downloadRecordPageQuery", command, new TypeReference<>() {
        });
        List<AdminDownloadRecordPageDTO> dtoList = result.getData().getList().stream().map(downloadConverter::toAdminDownloadRecordPageDTO).toList();
        return PageResult.success(dtoList, result.getData().getTotal());
    }


    @Operation(summary = "获取未下载且未过期的下载记录条数", security = {@SecurityRequirement(name = SecurityConstants.TOKEN_KEY)})
    @GetMapping("/getUnDownloadCount")
    public Result<Integer> getUnDownloadCount() {
        return OkHttpUtils.X.get(downloadServerUrl + "/download/record/getUnDownloadCount?downloaderName=" + SecurityUtils.X.getUser().getUsername(), new TypeReference<>() {
        }, new HashMap<>());
    }


    @Operation(summary = "更新下载记录下载状态", security = {@SecurityRequirement(name = SecurityConstants.TOKEN_KEY)})
    @PostMapping("/updateMethodRecordStatus")
    public Result<Boolean> updateMethodRecordStatus(@Validated @RequestBody UpdateDownloadRecordStatusCommand command) {
        return OkHttpUtils.X.post(downloadServerUrl + "/download/record/updateMethodRecordStatus", command, new TypeReference<>() {
        });
    }

    /**
     * 新增下载方法配置
     * @param command command
     * @param httpRequest httpRequest
     * @return  Result<Boolean>
     */
    @PostMapping("/addMethodConfig")
    public Result<Boolean> addMethodConfig(@Validated AddDownloadMethodCommand command, HttpServletRequest httpRequest) {
        MultipartHttpServletRequest mu = (MultipartHttpServletRequest) httpRequest;
        MultipartFile file = mu.getFile("file");
        if (Objects.isNull(file)) {
            return Result.failed("文件不能为空");
        }
        // 获取文件名
        String fileName = file.getOriginalFilename();
        // 获取文件后缀
        String prefix=fileName.substring(fileName.lastIndexOf("."));
        // 用uuid作为文件名，防止生成的临时文件重复
        final File excelFile;
        try {
            excelFile = File.createTempFile(UUID.randomUUID().toString(), prefix);
            // MultipartFile to File
            file.transferTo(excelFile);
            okhttp3.RequestBody fileBody  = okhttp3.RequestBody.create(MediaType.parse("application/from-data"), excelFile);
            MultipartBody requestBody = new MultipartBody.Builder()
                    .setType(MultipartBody.FORM)
                    .addFormDataPart("file", fileName, fileBody)
                    .addFormDataPart("methodName", command.getMethodName())
                    .addFormDataPart("methodCode", command.getMethodCode())
                    .addFormDataPart("systemCode", SYSTEM_CODE)
                    .addFormDataPart("limitType", Objects.isNull(command.getLimitType()) ? "0" : String.valueOf((command.getLimitType())))
                    .addFormDataPart("creator", SecurityUtils.X.getUser().getUsername())
                    .build();
            return OkHttpUtils.X.postByFormData(downloadServerUrl + "/download/method/config/addMethodConfig", requestBody, new TypeReference<>() {
            });
        } catch (IOException e) {
            log.error("添加下载方法配置异常,e", e);
            throw new BusinessException(ResultCode.SYSTEM_EXECUTION_ERROR);
        }

    }

    /**
     * 更新下载方法配置
     * @param request request
     * @param httpRequest httpRequest
     * @return Result<Boolean>
     */
    @PostMapping("/updateMethodConfig")
    public Result<Boolean> updateMethodConfig(@Validated UpdateDownloadMethodCommand request, HttpServletRequest httpRequest) {
        MultipartHttpServletRequest mu = (MultipartHttpServletRequest) httpRequest;
        MultipartFile file = mu.getFile("file");
        try {
            MultipartBody requestBody;
            if (Objects.nonNull(file)) {
                // 获取文件名
                String fileName = file.getOriginalFilename();
                // 获取文件后缀
                String prefix=fileName.substring(fileName.lastIndexOf("."));
                // 用uuid作为文件名，防止生成的临时文件重复
                final File excelFile = File.createTempFile(UUID.randomUUID().toString(), prefix);
                // MultipartFile to File
                file.transferTo(excelFile);
                okhttp3.RequestBody fileBody  = okhttp3.RequestBody.create(MediaType.parse("application/from-data"), excelFile);
                requestBody = new MultipartBody.Builder()
                        .setType(MultipartBody.FORM)
                        .addFormDataPart("file", fileName, fileBody)
                        .addFormDataPart("methodName", request.getMethodName())
                        .addFormDataPart("id", String.valueOf(request.getId()))
                        .addFormDataPart("limitType", Objects.isNull(request.getLimitType()) ? "0" : String.valueOf((request.getLimitType())))
                        .addFormDataPart("editor", SecurityUtils.X.getUser().getUsername())
                        .build();
            } else {
                requestBody = new MultipartBody.Builder()
                        .setType(MultipartBody.FORM)
                        .addFormDataPart("methodName", request.getMethodName())
                        .addFormDataPart("id", String.valueOf(request.getId()))
                        .addFormDataPart("limitType", Objects.isNull(request.getLimitType()) ? "0" : String.valueOf((request.getLimitType())))
                        .addFormDataPart("editor", SecurityUtils.X.getUser().getUsername())
                        .build();
            }
            return OkHttpUtils.X.postByFormData(downloadServerUrl + "/download/method/config/updateMethodConfig", requestBody, new TypeReference<>() {
            });
        } catch (IOException e) {
            log.error("更新下载方法配置异常,e", e);
            throw new BusinessException(ResultCode.SYSTEM_EXECUTION_ERROR);
        }
    }



}
